using System;
using System.Linq;
using static QntPlatform.Strategy.CmdCtrl.TrailingStep2;

namespace QntPlatform.Strategy.CmdCtrl
{


    /* 激进-突破信号：突破买入以持仓亏损的10% （20x杠杆）行情下跌0.5%止损，以为持仓盈利的30%进行平仓1/2，剩余追踪止盈
    20x杠杆
    止损为：购入价格*（1-0.5%）
    止盈为：（当前价格/购入价格)>0.015时平一半，剩余追踪
    思路：收到多空信号
    计算：止损、止盈
     */
    /// <summary>
    /// 激进-突破信号
    /// </summary>
    public class SurmountLv5 : CmdHandlePart, ICmdCtrl
    {

        /// 仓位最大可承受亏损
        decimal accountMaxLossRatio = 0.02m;
        /// 止损计算亏损率
        decimal stopLossRatio=0.005m;
        EventHandler<Ticker> ev;

       // public int Period { get; set; }
        //public bool IsLong { get; set; }
        public decimal ProfitRate1{get;set;}
        public SurmountLv5(StrategyBase parent) : base(parent)
        {
            ProfitRate1=0.015m;
        }

        public override void OnExit(Exception ex)
        {
            Exchange.TickerChangeEvent -= ev;
        }
        public bool Execute(CmdContext context)
        {
            var cmdVal = GetCmdValue<TradeCmd>(context.Cmd.Value);
            //判断趋势
            if (!trendCheck(cmdVal.Period, cmdVal.IsLong))
            {
                log.Debug("趋势错误忽略", context.CmdStr);
                return true;
            }

            //var ret = Exchange.GetRecordsAsync(cmdVal.Period);
            var account = Exchange.GetAccountAsync();
            var tck = Exchange.GetTickerAsync();

            //交易：仓位计算
            var nowPrice = tck.Result.Buy;
            //计算止损：数量，止损价，止损类型(固定）
            decimal stopLoss = StopLossCalc(nowPrice, cmdVal.IsLong);
            decimal buyAmount = AmountCalc(account.Result, stopLoss, nowPrice, cmdVal.IsLong);

            var id = cmdVal.IsLong ? Exchange.BuyAsync(buyAmount) : Exchange.SellAsync(-1, buyAmount);  // execTrade(DirectionTo.InFor(cmdVal.IsLong), buyAmount);
            //计算止盈：数量，止盈价，止盈类型(跟踪、固定)，止盈后动作(设置止损)
            var spl = new StopLoss(this, new StopLoss.StopLossInfo() { Sid = context.CmdStr.GetHashCode() + "", Amount = buyAmount, StopLossPrice = stopLoss, IsCloseBuy = cmdVal.IsLong, Info = id });
            var profitPrice = StopProfitCalc(nowPrice, cmdVal.IsLong);
            var fp = new TrailingStep2.FixedProfit(this) { Amount = buyAmount-Exchange.getAmount(buyAmount / 2), Price = profitPrice, IsLong = cmdVal.IsLong };
            fp.AfterFun = () => spl.Data.StopLossPrice = nowPrice;
            var tp = new TrailingProfit(this, new TrailingProfit.TrailingProfitData() { SourceOrderId = id.Result, Amount = Exchange.getAmount(buyAmount / 2), InPrice = nowPrice, CloseDirection = DirectionTo.CloseFor(cmdVal.IsLong) });
            tp.SetProfitRate(profitPrice);
            var isTpBegin = false;
            var fun = new MiddleGuoup<Ticker>()
                   .AddUse(p =>
                   {
                       var re = spl.Execute(p);
                       if (re) OnExit(null);
                       return re;
                   })
                   .AddUse(p =>
                   {
                       if (isTpBegin) return false;
                       var re = fp.Execute(p);
                       if (re)
                       {
                           isTpBegin = true;
                           spl.Data.StopLossPrice = nowPrice;
                       }
                       return false;
                   })
                   .AddRun(p =>
                   {
                       if (isTpBegin)
                       {
                           var re = tp.Execute(p);
                           if (re) OnExit(null);
                       }
                   })
                   .Bulid();
            ev = (p1, p2) => fun.Invoke(p2);
            Exchange.TickerChangeEvent += ev;
            //监控添加
            return true;
        }

        private decimal AmountCalc(Account account, decimal stopLoss, decimal nowPrice, bool isLong)
        {
            var longVal = isLong ? 1 : -1;
            var am = longVal * account.Balance * accountMaxLossRatio / (nowPrice - stopLoss);
            return Exchange.getAmount(am);
        }
        /// （当前价格/购入价格)>0.015时平一半，剩余追踪
        decimal StopProfitCalc(decimal price,bool isLong)
        {
           return ISysFun.CalcPriceByProfitRate(ProfitRate1, price,isLong);
        }
        /// 购入价格*（1-0.5%）
        private decimal StopLossCalc(decimal price, bool isLong)
        {
            var stopLoss=isLong?price*(1-stopLossRatio):price*(1+stopLossRatio);
            log.Debug(this.GetType().Name+"止损计算信息", new {stopLoss});
            return stopLoss;
        }

    }
}
